package trap

import (
	"cqrcsnmpserver/common/sender"
	"cqrcsnmpserver/linklist"
	"errors"
	"fmt"
	g "github.com/gosnmp/gosnmp"
	log "github.com/sirupsen/logrus"
	"net"
	"time"
)



func genMsgHeader(hostip string, packet *g.SnmpPacket)(msg string) {
	msg = ""
	msg = msg + fmt.Sprintf("%s CQRCB_SYSTEM %s\n" ,time.Now().Format("2006-01-02 15:04:05"), hostip)
	msg = msg +                    "PDU INFO:\n"
	msg = msg +                    "  MESSAGE TYPE: SNMP TRAP \n"
	msg = msg + fmt.Sprintf("  VERSION:  %s\n", packet.Version )
	msg = msg + fmt.Sprintf("  FROM: [%s]\n",hostip)
	msg = msg + fmt.Sprintf("  STATUS: [%s]\n",packet.Error)
	msg = msg + fmt.Sprintf("  MESSAGE ID: [%v]\n",packet.MsgID)
	msg = msg + fmt.Sprintf("  COMMUNITY: [%s	]\n",packet.Community)
	msg = msg + fmt.Sprintf("  INDEX: [%v]\n",packet.ErrorIndex)
	msg = msg + fmt.Sprintf("  REQUEST ID: [%v]\n",packet.RequestID)
	msg = msg + "TRAP VARIABLES:\n"
	return msg
}

func parseSnmpPack(hostip string, list *linklist.List, packet *g.SnmpPacket) {
	msg := genMsgHeader(hostip, packet)
	
	pdus := make([]*TrapPDU, 0)
	// 迭代解析每一个snmp报文
	for _, v := range packet.Variables {
		oidName := ""
		if name , err := global_mib_tree.FindNodeName(v.Name); err != nil {
			log.WithField("err", err ).Error("trans oid to name error")
			oidName = v.Name
		} else {
			oidName = name
		}

		switch v.Type {
		case g.OctetString:
			b := v.Value.([]byte)
			log.WithField("OID", v.Name).WithField("string", fmt.Sprintf("%s",b)).WithField("Type", v.Type).Info()
			pdu := TrapPDU{
				OID:   oidName,
				Type:  v.Type,
				Value: fmt.Sprintf("%s",b),
				Ts: time.Now().Format("2006-01-02 15:04:05"),
			}
			pdus = append(pdus, &pdu)
		case g.ObjectIdentifier:
			obj_id := fmt.Sprintf("%s",v.Value)
			obj_name := ""
			if name , err := global_mib_tree.FindNodeName(obj_id); err != nil {
				log.WithField("err", err ).Error("trans oid to name error")
				obj_name = obj_id
			} else {
				obj_name = name
			}

			pdu := TrapPDU{
				OID:   oidName,
				Type:  v.Type,
				Value: obj_name,
				Ts: time.Now().Format("2006-01-02 :04:05"),
			}
			pdus = append(pdus, &pdu)
		default:
			pdu := TrapPDU{
				OID:   oidName,
				Type:  v.Type,
				Value: v.Value,
				Ts: time.Now().Format("2006-01-02 :04:05"),
			}
			pdus = append(pdus, &pdu)
		}
	}
    tags := paesePdusToListMap(pdus)
	for _, tag := range tags {
			item := fmt.Sprintf("  SNMP-MIB::%v  value=%v: [%v]\n", tag["oid"], tag["type"], tag["value"])
			msg = msg + item
	}

	list.Append(msg)
	sender.Sends(hostip, msg)
}

func paesePdusToListMap(pdus []*TrapPDU) ([]map[string]string) {
	res := make([]map[string]string,0)
	for _, v := range pdus{
		res = append(res, map[string]string{"oid":v.OID, "type": fmt.Sprintf("%v",v.Type),"value":fmt.Sprintf("%v",v.Value),"ts":v.Ts})
	}
	return res
}


func BaseTrapHandler(packet *g.SnmpPacket, addr *net.UDPAddr) {
	log.WithField("addr", addr.IP.String()).Info("got trap package from")
	curList, ok := TrapMap[addr.IP.String()]
	if ok {
		log.WithField("address", addr.IP.String()).Info("address is exits.")
		parseSnmpPack( addr.IP.String(), curList, packet)
	} else {
		newList := linklist.NewList()
		TrapMap[addr.IP.String()] = newList
		parseSnmpPack( addr.IP.String(), newList, packet)
	}
}

func DelItem(ip string, index int64) (error) {
	curlist, ok := TrapMap[ip]
	if ok {
		curlist.RemoveAtIndex(index)
		if curlist.Length() <=0 {
			delete(TrapMap, ip)
		}
	} else {
		return errors.New(fmt.Sprintf("该IP【%s】没有在trap数据库中", ip))
	}
	return nil
}

func checkItem(data interface{}, pdu interface{}) (bool) {
	d := data.(TrapPDU)
	p :=  pdu.(*TrapPDU)
	if d.OID == p.OID && d.Ts == p.Ts && fmt.Sprintf("%v", d.Value) == fmt.Sprintf("%v",p.Value) &&  fmt.Sprintf("%v", d.Type) == fmt.Sprintf("%v",p.Type){
		return true
	} else {
		return false
	}
}